package com.opcode.nebulamobil.base.services;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import com.opcode.nebulamobil.information.ApplicationInfo;
import com.opcode.nebulamobil.information.dataforms.costadataforms.ConnectionStatus.ConnectionStatusInfo;
import com.opcode.nebulamobil.information.dataforms.costadataforms.SettingsDataForm;
import com.opcode.nebulamobil.base.interfaces.TryConnectionCommandListener;
import com.opcode.nebulamobil.base.interfaces.RequestListener;
import com.opcode.nebulamobil.information.dataforms.costadataforms.ConnectionStatus;
import com.opcode.nebulamobil.utility.JsonConverter;
import com.opcode.nebulamobil.utility.STSLog;

/**
 * Bu service sürekli olarak arka planda çalşarak bağlantı kurma, veri alma ve uzaktaki sunucuya veri gönderme işlerini yapacaktır.
 * @author Okan ERDOĞAN
 *
 * 16 Tem 2014
 */
public class ConnectionService extends Service implements RequestListener,TryConnectionCommandListener{
	
	
	//Referanslar
	private Thread connectionThread;
	private Socket socket;
	private PrintWriter pWriter;
	private ConnectionStatus connectionStatus;
	private String readData="",bufferData="";
	private Messenger client;
	private String fileName;
	private SharedPreferences aData = null;
	
    final Messenger mMessenger = new Messenger(new IncomingHandler());
	
	
    /**
     * Bir service ister startService ile ister bindService ile aktif hale getirilmiş olsun. Herzaman ilk olarak onCreate metodu çalıştırılır.
     */
	public void onCreate(){
		super.onCreate();
		/*
		 * Service oluşturulurken gerekli nesneler ve ayarlamalar yapılıyor.
		 * Bu service öncelikle STS uygulaması içerisinden gönderilecek olan requestlerin dinleyicisi olarak kendisini ayarlıyor.
		 */
		ApplicationInfo.setRequestListener(this);	
		ApplicationInfo.setTryConnectionCommandListener(this);
		
		
		/*
		 * Daha sonra da kendisinin baï¿½lantï¿½ ile ilgili ï¿½zelliklerini dinlemek isteyenlere aï¿½aï¿½ï¿½da oluï¿½turulan ConnectionStatus nesnesini gï¿½ndermek iï¿½in bu nesneyi oluï¿½turuyor.
		 */
		this.connectionStatus=new ConnectionStatus();
		
		/*
		 * Burada da service'in sunucuya baï¿½lanmak iï¿½in yapacaï¿½ï¿½ iï¿½leri yï¿½neten thread nesnesini oluï¿½turuyoruz.
		 * Bu nesne iï¿½erisindeki run metodu thread baï¿½latï¿½dï¿½ï¿½ï¿½nda tetiklenir.
		 * Run metodu iï¿½erisinde sonsuz olarak dï¿½nen bir dï¿½ngï¿½ bulunmaktadï¿½r.
		 */
		this.connectionThread=new Thread(new Runnable(){

			@Override
			public void run() {
				
				/*
				 * ï¿½lk olarak connetionStatus varsayï¿½lan bir deï¿½ere ayarlanï¿½yor.
				 * Bu deï¿½er bir serverï¿½n bulunmadï¿½ï¿½ï¿½ durumdur.
				 */
				connectionStatus.setConnectionInfoMessage("Sunucuya kurulmuş bir bağlantı bulunmuyor.");
				connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.SERVER_NOT_FOUND);
				
				/*
				 * Ayalarlanan connectionStatus deï¿½eri sharedPreferences'a kayï¿½t ediliyor. 
				 * Bï¿½ylece istenilen her yerden connectionstatus key'ini sharedpreferences'a vererek baï¿½lantï¿½ durumu ile ilgili bilgi almamï¿½z mï¿½mkï¿½n.
				 */
				createSharedPreferencesManager("sharedpreferences",getApplicationContext());
				writeToSharedPreferences("connectionStatus", JsonConverter.toJsonString(connectionStatus));

				/*
				 * Sonsuz döngü başlıyor.
				 */
				while(true){	
					
					System.out.println("ConnectionService Döngu-1");

						/*
						 * Burada connectionstatus elde edilerek baï¿½lantu durumunun CONNECTED olup olmadï¿½ï¿½ï¿½na bakï¿½lï¿½r.
						 * Bu dï¿½ngï¿½ baï¿½lantï¿½ durumu CONNECTED olana kadar dï¿½ner. 
						 * Ancak dï¿½ngï¿½nï¿½n her bir turu neticesinde baï¿½lantï¿½ kurulmamï¿½ï¿½sa bir dialog aï¿½ï¿½larak kullanï¿½cï¿½nï¿½n dï¿½ngï¿½yï¿½ bir kez daha ï¿½alï¿½ï¿½tï¿½rmasï¿½ istenir.
						 * Bunu yapmak iï¿½in tekrar dene butonuna basmanï¿½z yeterli.
						 */
						while(!((ConnectionStatus) JsonConverter.fromJsonString(readFromSharedPreferences("connectionStatus", null), ConnectionStatus.class)).getConnectionStatusInfo().equals(ConnectionStatusInfo.CONNECTED)){
						
							System.out.println("ConnectionService Döngu-2");

							/*
							 * Daha ï¿½nce sharedpreferences'a kayï¿½t edilen settingsInfo bilgileri elde ediliyor.
							 * Bu bilgiler iï¿½inde baï¿½lanï¿½lmak istenen sunucunun ip ve port deï¿½erleri bulunuyor.
							 */
							createSharedPreferencesManager("sharedpreferences",getApplication());
							String settingsDataFormAsJson=readFromSharedPreferences("settingsInfo", null);	
							SettingsDataForm settingsInfo=(SettingsDataForm) JsonConverter.fromJsonString(settingsDataFormAsJson, SettingsDataForm.class);
							
							try {
								/*
								 * Uygulama ilk aï¿½ï¿½ldï¿½ï¿½ï¿½nda ayar bilgisi iï¿½erisinde ip ve port bilgilerinin olup olmadï¿½ï¿½ï¿½na bakar.
								 * Eï¿½er bu veriler yosa STS uygulamasï¿½ bu durumdan haberdar olarak kullanï¿½cï¿½ya ip ve port bilgilerini girmesi iï¿½in ayarlar ekranï¿½nï¿½n aï¿½ar.
								 */
								if(settingsInfo!=null){
									/*
									 * Baï¿½lantï¿½,veri okuma ve sunucuya yazma iï¿½leri iï¿½in gereken nesneler oluï¿½turuluyor.
									 */
									
									 InetAddress addr = InetAddress.getByName(settingsInfo.getServerIp());
									 SocketAddress sockaddr = new InetSocketAddress(addr, settingsInfo.getServerPort());

									socket=new Socket();
									
									socket.connect(sockaddr, 10000);

									/*
									 * Socket'in timeout sï¿½resi ayarlanï¿½yor.
									 * Time out sï¿½resini 0 yapmak demek herhangi bir sï¿½re verilmeden sonsuza kadar bekle demektir.
									 */
								//	socket.setSoTimeout(0);
									
									/*
									 * Uzak sunucuya veri yazmak iï¿½in pWriter nesnesi kullanï¿½lacaktï¿½r.
									 */
									pWriter=new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"),true);
									/*
									 * Socket'in sunucuya baï¿½lanï¿½ baï¿½lanmadï¿½ï¿½ï¿½ kontrol ediliyor.
									 * Eï¿½er baï¿½lantï¿½ kurulmuï¿½sa gerekli dï¿½zenlemeler ve bilgilendirmeler yapï¿½lï¿½yor.
									 */
									if(socket.isConnected()){
										
										/*
										 * Baï¿½lantï¿½ kurulmuï¿½sa bufferedReader nesnesi oluï¿½turularak sunucudan veri okunmaya baï¿½lanï¿½yor.
										 */
										readData(new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8")));
									}else{
										Log.i("ConnectionService", "Bağlantı kurulamadı.");
									}
									
								/*
								 * Sunucuya baï¿½lanmak iï¿½in ip ve port bilgileri settings'ten elde edilememiï¿½se kodun bu bï¿½lï¿½mï¿½ ï¿½alï¿½ï¿½ï¿½r.
								 * Baï¿½lantï¿½ durumu SERVER_NOT_FOUND olarak uygulamaya bildirilir.
								 * Bu bildirim ile uygulama bir dialog aï¿½arak sunucu bilgilerinin girilmesini ister.
								 * Bu esnada da connectionThread uyku moduna geï¿½er.
								 * Kullanï¿½cï¿½ aï¿½ï¿½lan dialogtan sunucuya ait ip ve port bilgilerini girdikten sonra kaydet butonuna basarak connectionThread'i uyandï¿½rmï¿½ï¿½ olur.
								 * Bï¿½ylece baï¿½lantï¿½ yeni sunucu bilgileri ile tekrar denenir.
								 */
								}else{
									connectionStatus.setConnectionInfoMessage("Sunucuya bağlanmak için ip ve port bilgisi bulumamadı.");
									connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.SERVER_NOT_FOUND);
									pingToConnectionListeners(connectionStatus);

									try {
										synchronized(connectionThread){
											Log.i("ConnectionService", "Sunucuya baï¿½lanmak için ip ve port bilgisi bulumamadï¿½.Thread bekletildi.");
											connectionThread.wait();
										}
									
									} catch (InterruptedException e) {
										STSLog.writeLog(e,this.getClass().getCanonicalName(),"Thread bekletilmeye çalışılırken hata meydana geldi.");														
									}
								}
								
							} 
							/*
							 * Karï¿½ï¿½ tarafta verilen adreste bilinmeyen bir sunucu olduï¿½unda bu catch bloï¿½u ï¿½alï¿½ï¿½ï¿½r. 
							 */
							catch (UnknownHostException e1) {
								connectionStatus.setConnectionInfoMessage("Bilinmeyen sunucu.Lütfen sunucu bilgilerini kontrol ediniz.");
								connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.SERVER_NOT_FOUND);
								pingToConnectionListeners(connectionStatus);
								
								STSLog.writeLog(e1,this.getClass().getCanonicalName(),"Bilinmeyen sunucu hatası");	
								
								try {
									synchronized(connectionThread){
										Log.i("ConnectionService", settingsInfo.getServerIp()+":"+settingsInfo.getServerPort()+" adresinde sunucu bulunamadı.Thread bekletildi.");
										connectionThread.wait();
									}
								
								} catch (InterruptedException e) {
									STSLog.writeLog(e,this.getClass().getCanonicalName(),"Thread bekletilmeye çalışılırken hata meydana geldi.");														
								}
																					
							
							}
							
							/*
							 * Socket sunucu ile baï¿½lantï¿½ kuramadï¿½ï¿½ï¿½nda catch bloï¿½una dï¿½ßlï¿½r.
							 */
							catch(SocketException e1){
								
								
								connectionStatus.setConnectionInfoMessage(settingsInfo.getServerIp()+":"+settingsInfo.getServerPort()+" adresine bağlantıda zaman aşımı yaşandı.");
								connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.SERVER_NOT_FOUND);
								pingToConnectionListeners(connectionStatus);
								
								STSLog.writeLog(e1,this.getClass().getCanonicalName(),"Sunucu bağlantısı zaman aşımı hatası");	
								
								try {
									synchronized(connectionThread){
										Log.i("ConnectionService", settingsInfo.getServerIp()+":"+settingsInfo.getServerPort()+" adresine 60 sn. boyunca baï¿½lanï¿½lamadï¿½.Lï¿½tfen tekrar deneyiniz.");
										connectionThread.wait();
									}
								
								} catch (InterruptedException e) {
									STSLog.writeLog(e,this.getClass().getCanonicalName(),"Thread bekletilmeye ï¿½alï¿½ï¿½ï¿½lï¿½rken hata meydana geldi.");														
								}
								
							}
							
							/*
							 * Sunucuya baï¿½lantï¿½ iï¿½in gerekli bilgiler var, ancak karï¿½ï¿½ tarafta dinleme yapan bir sunucu yoksa IOException fï¿½rlatï¿½lï¿½r.
							 * Bu durumda da yine gerekli bilgilendirmeler kullanï¿½cï¿½nï¿½n tekrar baï¿½lantï¿½ kurmayï¿½ denemesi istenir.	
							 * Bu sï¿½re zarfï¿½nda da connectionThread bekletilir.
							 * Kullanï¿½cï¿½nï¿½n aï¿½ï¿½lan dialogdan tekrar dene butonuna basmasï¿½ connectionThread'i uyandï¿½racaktï¿½r.
							 */
							catch (IOException e1) {
								Log.i("ConnectionService", settingsInfo.getServerIp()+":"+settingsInfo.getServerPort()+" adresinde sunucu bulunamadï¿½.");
								connectionStatus.setConnectionInfoMessage(settingsInfo.getServerIp()+":"+settingsInfo.getServerPort()+" adresinde sunucu bulunamadı.");
								connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.SERVER_NOT_FOUND);
								pingToConnectionListeners(connectionStatus);
								
								try {
									synchronized(connectionThread){
										Log.i("ConnectionService", settingsInfo.getServerIp()+":"+settingsInfo.getServerPort()+" adresinde sunucu bulunamadï¿½.Thread bekletildi.");
										connectionThread.wait();
									}
								
								} catch (InterruptedException e) {
									STSLog.writeLog(e1,this.getClass().getCanonicalName(),"Thread bekletilmeye ï¿½alï¿½ï¿½ï¿½lï¿½rken hata meydana geldi.");														
								}
							}
						}
					}
				}	
		});
		
	}
	
	
	
	/**
	 * ConnectionService eï¿½er startService komutu ile aktif hale getirilmiï¿½se onCreate metodundan sonra bu metod ï¿½alï¿½ï¿½ï¿½r.
	 * Bu metod ï¿½alï¿½ï¿½ï¿½r ï¿½alï¿½ï¿½maz ilk iï¿½ olarak baï¿½lantï¿½ thread'ini ï¿½alï¿½ï¿½tï¿½rï¿½r.
	 * Eï¿½er baï¿½lantï¿½ thread'i hali hazï¿½rda ï¿½alï¿½ï¿½ï¿½yorsa herhangi bir iï¿½lem yapmaz.
	 */
	public int onStartCommand(Intent intent,int flags,int startId){
		super.onStartCommand(intent, flags, startId);
		
		Log.i("ConnectionService", "Baï¿½lantï¿½ service'i baï¿½latï¿½lï¿½yor.");	
    	
		if ( connectionThread.getState() == Thread.State.NEW ){
			this.connectionThread.start();
			Log.i("ConnectionService", "Thread baï¿½latï¿½ldï¿½.");	
		}else{
			tryConnectionAgain();
			Log.i("ConnectionService", "ConnectionThread hali hazï¿½rda ï¿½alï¿½ï¿½ï¿½yor.");		
		}
		return START_NOT_STICKY;
	}
	
	
	
	/**
	 * ConnectionService eï¿½er bindService komutu ile aktif hale getirilmiï¿½se onCreate metodundan sonra bu metod ï¿½alï¿½ï¿½ï¿½r.
	 */
	public IBinder onBind(Intent intent) {
		Log.i("ConnectionService", "Connection service bind yapï¿½ldï¿½.");
        return mMessenger.getBinder();
    }
	
	
	/**
	 * ConnectionService unbindService komutu ile pasif hale getirilmiï¿½se bu metod ï¿½alï¿½ï¿½ï¿½r.
	 * Uygulamayï¿½ tamamen ï¿½ldï¿½rmek iï¿½in bu metod iï¿½erisinden onDestroy metoduna yï¿½nelndirme yapmamï¿½z gereklidir.
	 */
	public boolean onUnbind (Intent intent){
		Log.i("ConnectionService", "Connection service unbind yapï¿½ldï¿½.");
		return true;
	}
	
	
	/**
	 * ConnectionService iï¿½erisinden veya bir client aracï¿½lï¿½ï¿½ï¿½yla service durdurulmuï¿½sa bu metod tetiklenir.
	 * Service kapanmadan ï¿½nce yapï¿½lmasï¿½ istenen iï¿½ler burada yapï¿½lmalï¿½dï¿½r.
	 */
	public void onDestroy(){
		super.onDestroy();
		try {
			
			if(socket!=null){
				socket.close();
			}
			Thread.currentThread().interrupt();
			this.stopForeground(true);
			this.stopSelf();
		} catch (IOException e) {
			STSLog.writeLog(e,this.getClass().getCanonicalName(),"Socket kapatï¿½lï¿½rken hata meydana geldi.");														
		}
		Log.i("ConnectionService", "Baï¿½lantï¿½ service'i kapatï¿½lï¿½yor..");
	}
	
	
	
	
	/**
	 * Uzak sunucuya bir socket baï¿½lantï¿½sï¿½ baï¿½arï¿½lï¿½ bir ï¿½ekilde kurulmuï¿½sa bu metod ï¿½aï¿½rï¿½lï¿½r.
	 * Bu metod parametre olarak almï¿½ï¿½ olduï¿½u bufferedreader nesnesi ile sunucudan veri okumasï¿½ yapar.
	 * Okuduï¿½u verileri de ilgili yerlere bildirir.
	 * @param bReader
	 */
	public void readData(BufferedReader bReader){
		
		/*
		 * ï¿½ncelikle parametre olarak gelen bReader nesnesinin null olup olmamasï¿½na bakï¿½ldï¿½.
		 * Bu nesne null ise hiï¿½bir veri okumasï¿½ yapï¿½lamayacaï¿½ï¿½ndan dolayï¿½ hiï¿½bir kod iï¿½letilmeden metodun sonuna eriï¿½ilir.
		 */
		if(bReader!=null){
			
			/*
			 * Bu metod ï¿½aï¿½rï¿½ldï¿½ï¿½ï¿½na gï¿½re baï¿½arï¿½lï¿½ bir sunucu baï¿½lantï¿½sï¿½ kurulmuï¿½ demektir.
			 * Bu nedenle baï¿½lantï¿½nï¿½n kurulduï¿½u bilgisi aktiviteye bildirilir.
			 */
			Log.i("ConnectionService", "Bağlantı kuruldu.");
			connectionStatus.setConnectionInfoMessage("Bağlantı kuruldu.");
			connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.CONNECTED);
			
			/*
			 * Bu metod baï¿½lantï¿½ ile ilgili durumlarï¿½ aktiviteye bildirmek iï¿½in kullanï¿½lï¿½r.
			 * Ancak metodun yaptï¿½ï¿½ï¿½ ilk iï¿½ baï¿½lantï¿½ durumu bilgisini sharedpreferences'a da kayï¿½t etmektir.
			 */
			pingToConnectionListeners(connectionStatus);

			
			try {
			
				/*
				 * Burada bir dï¿½ngï¿½ oluï¿½turularak socket ï¿½zerinden gelen veriler okunur.
				 * Bu dï¿½ngï¿½ uzak sunucu ile baï¿½lantï¿½ devam ettiï¿½i sï¿½rece devam eder.
				 */
				while((readData=bReader.readLine())!=null){
					/*
					 * Okunan veriler bufferData ï¿½zerine kayï¿½t edilir.
					 */
					bufferData=bufferData+readData+'\n';
					
					if(ApplicationInfo.getResponseListener()!=null){
						
						/*
						 * Okunan her bir satï¿½rdaki veri response listener olan sï¿½nï¿½flara bildirilir.
						 */
						ApplicationInfo.getResponseListener().responseCame(readData);
						System.out.println(ApplicationInfo.getResponseListener().toString());
					}
					
					if(ApplicationInfo.getAlertListener()!=null){
						
						/*
						 * Okunan her bir satï¿½rdaki veri response listener olan sï¿½nï¿½flara bildirilir.
						 */
						ApplicationInfo.getAlertListener().alertCame(readData);
					}
					
					Log.i("readData()", readData);

				}
				
				/*
				 * Uzak sunucu kapatï¿½lï¿½rsa sonsuz veri okuma dï¿½ngï¿½sï¿½nden ï¿½ï¿½kï¿½lï¿½r.
				 * Bu durumda bReader ve socket nesnelerimizin baï¿½lantï¿½larï¿½ da kopartï¿½larak ilk duruma gelmeleri saï¿½lanï¿½r.
				 */
				try {
					bReader.close();
					socket.close();

					Log.i("ConnectionService", "Bağlantı koptu.");
					
					/*
					 * Baï¿½lantï¿½nï¿½n kopma durumu aktiviteye bildirilir. 
					 */
					connectionStatus.setConnectionInfoMessage("Bağlantı koptu.");
					connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.CONNECTION_LOST);
					pingToConnectionListeners(connectionStatus);
					
					/*
					 * Baï¿½lantï¿½ koptuï¿½u iï¿½in tekrar dene tuï¿½una basï¿½lana kadar connectionThread uyku moduna geï¿½er.
					 */
					synchronized(connectionThread){
						try {
							Log.i("ConnectionService", "Baï¿½lantï¿½ koptu.Thread bekletildi.");
							connectionThread.wait();
						} catch (InterruptedException e) {
							STSLog.writeLog(e,this.getClass().getCanonicalName(),"Baï¿½lantï¿½ thread'i bekletme moduna geï¿½irilirken hata meydana geldi.");														
						}
					}
					
				} catch (IOException e1) {
					STSLog.writeLog(e1,this.getClass().getCanonicalName(),"BufferedReader ve Socket kapatï¿½lï¿½rken hata meydana geldi.");														
				}
			} 
			/*
			 * Uzak sunucudan veri okunurken bir problemin meydana gelmesi durumunda IOException istisnasï¿½ fï¿½rlatï¿½lï¿½r.
			 * Bu istisnanï¿½n fï¿½rlatï¿½lmasï¿½nï¿½n ardï¿½ndan baï¿½lantï¿½ durumu olarak CONNECTION_LOST set edilir.
			 * Bï¿½ylece kullanï¿½cï¿½nï¿½n tekrar dene butonuna basarak yeni bir baï¿½lantï¿½ kurmasï¿½ istenir.
			 */
			catch (IOException e) {

				/*
				 * Baï¿½lantï¿½ problemi meydana geldiï¿½inden dolayï¿½ bReader ve socket nesneleri kapatï¿½lï¿½yor.
				 */
				try {
					bReader.close();
					socket.close();
					
					Log.i("ConnectionService", "Veri okumada problem meydana geldi.");					
					connectionStatus.setConnectionInfoMessage("Veri okumada problem meydana geldi.");
					connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.CONNECTION_LOST);
					
					pingToConnectionListeners(connectionStatus);
					
					/*
					 * Hata meydana geldiï¿½inden dolayï¿½ baï¿½lantï¿½ threadi uyku moduna geï¿½iyor.
					 * Kullanï¿½cï¿½ya baï¿½lantï¿½nï¿½n koptuï¿½unu bildiren dialogdan tekrar dene butonuna basmasï¿½ durumunda connectionThread uyanacak ve yeniden baï¿½lantï¿½ kurmaya ï¿½alï¿½ï¿½acaktï¿½r.
					 */
					try {
						synchronized(connectionThread){
							Log.i("ConnectionService", "Baï¿½lantï¿½ koptu.Thread bekletildi.");
							connectionThread.wait();
						}	
					} catch (InterruptedException e2) {
						STSLog.writeLog(e,this.getClass().getCanonicalName(),"Baï¿½lantï¿½ thread'i bekletme moduna geï¿½irilirken hata meydana geldi.");
					}
				} catch (IOException e1) {
					STSLog.writeLog(e1,this.getClass().getCanonicalName(),"BufferedReader ve Socket kapatï¿½lï¿½rken hata meydana geldi.");														
				}
			}
		}
	
	}
	
	
	
	/**
	 * Bu metod ï¿½aï¿½rï¿½ldï¿½ï¿½ï¿½ zaman parametre olarak almï¿½ï¿½ olduï¿½u connectionStatus nesnesini ilgili baï¿½lantï¿½ dinleyicilerine gï¿½nderir.
	 * @param connectionStatus
	 */
	public void pingToConnectionListeners(ConnectionStatus connectionStatus){
		
		/*
		 * connectionstatus nesnesini sharedpreferences'a kayï¿½t ediyor. Bï¿½ylece baï¿½lantï¿½ durumunu sorgulamak isteyen sï¿½nï¿½flar bu veriyi elde edebiliyorlar.
		 */
		createSharedPreferencesManager("sharedpreferences",getApplicationContext());
		writeToSharedPreferences("connectionStatus", JsonConverter.toJsonString(connectionStatus));
		
		/*
		 * Baï¿½lantï¿½ durumunu dinleyen dinleyiciler elde edilere baï¿½lantï¿½ durumu bildirimi yapï¿½lï¿½yor.
		 */
		
		if(ApplicationInfo.getConnectionListener()!=null){
			
			ApplicationInfo.getConnectionListener().connectionStatusChanged(connectionStatus);

		}else{
			connectionListenerNotFound("pingToConnectionListeners");
		}
		

	}
	
	

	private void connectionListenerNotFound(String whoCantFoundConnectionlistener){
		Log.i("ConnectionService", whoCantFoundConnectionlistener+ " baï¿½lantï¿½ durumu dinleyicisi bulamadï¿½.");	
		this.stopSelf();
		this.startService(new Intent(this.getApplicationContext(),ConnectionService.class));
		//this.startActivity(new Intent(this,FragmentActivityBase.class));
	}
	


	/**
	 * Aktiviteden bir request gï¿½nderildiï¿½i zaman bu metod tetiklenir.
	 */
	@Override
	public void jsonRequestCame(String jsonString) {
		
		Log.i("ConnectionService:", jsonString);

		/*
		 * Uzak sunucuya veri gï¿½ndermek iï¿½in kullanï¿½lacak olan pWriter nesnesinin null olup olmadï¿½ï¿½ï¿½na bakï¿½lï¿½yor.
		 * Bu nesnesinin null olmasï¿½ durumunda yeniden baï¿½lantï¿½ kurulmasï¿½ istenecektir.
		 * Bunun iï¿½in de baï¿½lantï¿½ durumu dinleyicilerine SERVER_NOT_FOUND mesajï¿½ gï¿½nderilir.
		 * Bu mesajï¿½ alï¿½nï¿½nca bir dialog aï¿½ï¿½lï¿½r ve tekrar dene butonuna basï¿½larak connectionThread uyandï¿½rï¿½lï¿½r. Bï¿½ylece bir kez daha baï¿½lantï¿½ talebi gï¿½nderilir.
		 */
		if(pWriter!=null){
			
			/*
			 * Bu kod parï¿½asï¿½ ile uzak sunucuya mesaj gï¿½nderilmiï¿½ olur.
			 */
			this.pWriter.println(jsonString);	
			
			/*
			 * Her bir mesaj gï¿½nderildikten sonra pWriter'da herhangi bir hatanï¿½n olup olmadï¿½ï¿½ï¿½ kontrol edilir.
			 * Herhangi bir hata tespit edilirse aï¿½aï¿½ï¿½daki if ï¿½artï¿½ ï¿½alï¿½ï¿½ï¿½r ve yeniden baï¿½lantï¿½ kurulmasï¿½ istenir.
			 */
			if(pWriter.checkError()){
				Log.i("ConnectionService", "Bağlantı koptu.Tekrar deneyiniz.");
				
				connectionStatus.setConnectionInfoMessage("Bağlantı koptu.Tekrar deneyiniz.");
				connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.CONNECTION_LOST);
				
				createSharedPreferencesManager("sharedpreferences",getApplicationContext());
				writeToSharedPreferences("connectionStatus", JsonConverter.toJsonString(connectionStatus));
				pingToConnectionListeners(connectionStatus);

				/*if(ApplicationInfo.getConnectionListener()!=null){
					
					ApplicationInfo.getConnectionListener().connectionStatusChanged(connectionStatus);

				}else{
					connectionListenerNotFound("jsonRequestCame1");

				}*/
				
			}
		}else
			/*
			 * pWriter nesnesinin null olmasï¿½ durumunda bu kod ï¿½alï¿½ï¿½ï¿½r.
			 */
			{
			Log.i("ConnectionService", "Bağlantısı problemi meydana geldi.Tekrar deneyiniz.");
			
			connectionStatus.setConnectionInfoMessage("Bağlantısı problemi meydana geldi.Tekrar deneyiniz.");
			connectionStatus.setConnectionStatusInfo(ConnectionStatusInfo.SERVER_NOT_FOUND);
			
			createSharedPreferencesManager("sharedpreferences",getApplicationContext());
			writeToSharedPreferences("connectionStatus", JsonConverter.toJsonString(connectionStatus));
			pingToConnectionListeners(connectionStatus);

			/*if(ApplicationInfo.getConnectionListener()!=null){

				ApplicationInfo.getConnectionListener().connectionStatusChanged(connectionStatus);

			}else{
				connectionListenerNotFound("jsonRequestCame2");

			}*/

		}
	}


	
	/**
	 * Sunucuya Baï¿½lantï¿½,veri okuma veya veri yazma konularï¿½nda herhangi bir problemin meydana gelmesi durumunda yeniden baï¿½lantï¿½ kurulmasï¿½ istenir.
	 * Bu yeniden baï¿½lantï¿½ kurulmasï¿½ talebi bir dialog ï¿½zerinden tekrar dene butonuna basï¿½larak yapï¿½lï¿½r.
	 * Bu butona basï¿½lmasï¿½ durumunda ise aï¿½aï¿½ï¿½da metod tetiklenerek uykuda olan baï¿½lantï¿½ thread'i yeniden ï¿½alï¿½ï¿½tï¿½rï¿½lï¿½r.
	 */
	@Override
	public void tryConnectionAgain() {
		synchronized(connectionThread){
			this.connectionThread.notifyAll();
		}

	}

	
	
	/**
	 * Bir sharedPreferences nesnesi elde etmek iï¿½in kullanï¿½lan metoddur.
	 * Bu metod neticesinde elde edilen aData nesnesi ile uygulamada bazï¿½ veriler sharedPreferences iï¿½ine kayï¿½t edilebilir.
	 * Bu projede sharedPreferences'a kayï¿½t edilen verilen varsayï¿½lan olarak baï¿½ka uygulamalarï¿½n eriï¿½imine kapatï¿½lmï¿½ï¿½tï¿½r.
	 * Ancak istenirse bu veriler herkese aï¿½ï¿½k hale getirilebilir.
	 * @param fileName
	 * @param context
	 */
	public void createSharedPreferencesManager(String fileName,Context context){
		this.fileName=fileName;
		this.aData= context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
	}
	
	
	/**
	 * Parametre olarak verilen key ve value verilerine gï¿½re sharedPreferences'a veri kaydetmek iï¿½in kullanï¿½lï¿½r.
	 * @param key
	 * @param value
	 */
	public void writeToSharedPreferences(String key,boolean value){
		SharedPreferences.Editor prefEditor = aData.edit();
        prefEditor.putBoolean(key, value);
        prefEditor.commit();
	}
	
	
	/**
	 * SharedPreferences'a bir key ile kayï¿½t edilen verileri yine aynï¿½ key ile elde etmeyi saï¿½lar.
	 * Bu metodun geri dï¿½nï¿½ï¿½ tipi boolean'dï¿½r.
	 * @param key
	 * @param defValue
	 * @return
	 */
	public boolean readFromSharedPreferences(String key,boolean defValue){
		boolean value=aData.getBoolean(key, defValue);
		return value;
	}
	
	
	/**
	 * String tipindeki verilerin sharedPreferences'a kayï¿½t edilmesini saï¿½layan metoddur.
	 * @param key
	 * @param value
	 */
	public void writeToSharedPreferences(String key,String value){
		SharedPreferences.Editor prefEditor = aData.edit();
        prefEditor.putString(key, value);
        prefEditor.commit();
	}
	
	
	/**
	 * String tipindeki verilerin sharedPreferences'tan elde edilmesini saï¿½layan metoddur.
	 * @param key
	 * @param defValue
	 * @return
	 */
	public String readFromSharedPreferences(String key,String defValue){
		String value=aData.getString(key, defValue);
		return value;
	}
	
	
	
	
	
	/**
	 * Bu sï¿½nï¿½f, aktiviteden gelen mesajlarï¿½ almak iï¿½in kullanï¿½lacaktï¿½r.
	 * Aktiviteden mesaj geldiï¿½inde gelen mesaja cevap verebileceï¿½imiz bir client'a sahip oluruz.
	 * Daha sonra bu client ï¿½zerinden aktiviteye istediï¿½imiz mesajï¿½ gï¿½nderebiliriz.
	 * @author Okan ERDOï¿½AN
	 *
	 * 16 Tem 2014
	 */
	class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) { 	
        	
        	if(msg.getData().get("welcome")!=null){
        		
        		
				Log.i("ConnectionService","ConnectionService'e welcome mesajï¿½ geldi."+ msg.getData().get("welcome").toString());	
				
            	client=msg.replyTo;
            	
            	Bundle data = new Bundle();
            	data.putString("welcome","Hello Activity");
            	
                Message message = Message.obtain();
        		message.setData(data);            	
        		
        		try {
        			if(client!=null){
        				client.send(message);	
        			}
        		} catch (RemoteException e) {
					STSLog.writeLog(e,this.getClass().getCanonicalName(),"Client mesaj gï¿½nderirken hata meydana geldi.");														
        		}
        		        		
        	}else if(msg.getData().get("personalListReq")!=null){
				Log.i("ConnectionService", "ConnectionService'e personelRequest mesajï¿½ geldi."+msg.getData().get("personalListReq").toString());	
        		
        	}else if(msg.getData().get("orderRequest")!=null){
        		//OrderRequest orderRequest=(OrderRequest) msg.getData().get("orderRequest");
				Log.i("ConnectionService","ConnectionService'e orderRequest mesajï¿½ geldi."+ msg.getData().get("orderRequest").toString());	
        		jsonRequestCame(msg.getData().get("orderRequest").toString());
        	}
        }

    }
}
